package com.shun.common.exception;

import com.shun.common.R;
import com.shun.common.RC;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.dao.DuplicateKeyException;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Component
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 拦截非法参数异常
     * @param validException
     * @return
     */
    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class, ConstraintViolationException.class})
    @ResponseBody
    public R bodyValidExceptionHandler(Exception validException) {
        log.error("参数校验异常， 异常信息：{}", validException.getMessage(), validException);
        if (validException instanceof MethodArgumentNotValidException) {
            List<String> errorsMsg = ((MethodArgumentNotValidException) validException).getBindingResult()
                    .getFieldErrors().stream().map(o -> {
                        return o.getField() + ":" + o.getDefaultMessage();
                    }).collect(Collectors.toList());
            return RC.SYSTEM_VALID_PARAM.toR(errorsMsg.toString());
        } else if (validException instanceof BindException) {
            List<String> errorsMsg = ((MethodArgumentNotValidException) validException).getBindingResult()
                    .getFieldErrors().stream().map(o -> {
                        return o.getField() + ":" + o.getDefaultMessage();
                    }).collect(Collectors.toList());
            return RC.SYSTEM_VALID_PARAM.toR(errorsMsg.toString());
        } else if (validException instanceof ConstraintViolationException) {
            List<String> errorsMsg = ((ConstraintViolationException) validException).getConstraintViolations()
                    .stream().map(ConstraintViolation::getMessage)
                    .collect(Collectors.toList());
            return RC.SYSTEM_VALID_PARAM.toR(errorsMsg.toString());
        }
        return RC.SYSTEM_VALID_PARAM.toR(validException.toString());
    }

    /**
     * 拦截自定义业务异常信息
     * @param e
     * @return
     */
    @ExceptionHandler(ShunBizException.class)
    @ResponseBody
    public R exception(ShunBizException e) {
        log.error("异常信息 :{}", e.getMessage(), e);
        return e.toR();
    }

    /**
     * 拦截数据库异常信息
     * @param e
     * @return
     */
    @ExceptionHandler(SQLIntegrityConstraintViolationException.class)
    @ResponseBody
    public R exception(SQLException e) {
        log.error("数据库异常:{}", e.getMessage());
        return R.builder().code(e.getErrorCode()+"").msg("数据异常").build();
    }

    /**
     * 拦截数据事务异常信息
     * @param e
     * @return
     */
    @ExceptionHandler(DuplicateKeyException.class)
    @ResponseBody
    public R exception(DuplicateKeyException e) {
        log.error("数据重复异常:{}", e.getMessage());
        return RC.DB_DUP_ERROR.toR();
    }

    /**
     * 拦截未定义全局异常信息
     * @param e
     * @return
     */
    @ExceptionHandler(SQLException.class)
    @ResponseBody
    public R sqlexception(SQLException e) {
        e.printStackTrace();
        log.error("异常信息 :{}", e.getMessage(), e);
        return RC.UNKNOW.toR("提交数据异常！");
    }

    /**
     * 拦截未定义全局异常信息
     * @param e
     * @return
     */
    @ExceptionHandler(Exception.class)
    @ResponseBody
    public R exception(Exception e) {
        e.printStackTrace();
        log.error("异常信息 :{}", e.getMessage(), e);
        return RC.UNKNOW.toR(e.getMessage());
    }
}
